package com.wry.im.handler;

import cn.hutool.core.date.DateUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <h1> 服务端消息处理器 <h1>
 *
 * @author wry
 * @since 2023/4/27 14:50
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class MessageServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static final Map<Object, Channel> channelMap = new ConcurrentHashMap<>();

    /**
     * 每当从服务端读到客户端写入信息时,将信息转发给其他客户端的Channel.
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        log.debug("MessageServerHandler - 执行了...");
        //消息处理
        message(ctx, msg.text(), DateUtil.now());
    }

    /**
     * 每当服务端收到新的客户端连接时,客户端的channel存入ChannelGroup列表中,并通知列表中其他客户端channel
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        // 获取连接的channel
        Channel incomming = ctx.channel();
        //通知所有已经连接到服务器的客户端，有一个新的通道加入
//        for(Channel channel:channelGroup){
//            channel.writeAndFlush("[SERVER]-"+incomming.remoteAddress()+"加入\n");
//        }
        channelGroup.add(incomming);
        channelMap.put(ctx.channel().id(), ctx.channel());
        log.info("客户端 {} - 加入成功，当前连接人数-[{}]",ctx.channel().id(), channelMap.size());
    }

    /**
     * 每当服务端断开客户端连接时,客户端的channel从ChannelGroup中移除,并通知列表中其他客户端channel
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        //获取连接的channel
        /*Channel incomming = ctx.channel();
        for(Channel channel:channelGroup){
            channel.writeAndFlush("[SERVER]-"+incomming.remoteAddress()+"离开\n");
        }*/
        //从服务端的channelGroup中移除当前离开的客户端
        channelGroup.remove(ctx.channel());
        //从服务端的channelMap中移除当前离开的客户端
        Collection<Channel> col = channelMap.values();
        while (col.contains(ctx.channel())) {
            col.remove(ctx.channel());
            channelMap.remove(ctx.channel().id(), ctx.channel());
            log.info("客户端 {} - 连接删除成功，当前连接人数-[{}]", ctx.channel().id(), channelMap.size());
        }
//        socketChannel.closeFuture().addListener((ChannelFutureListener) channelFuture -> {
//            log.info("channel close future  {}",channelFuture);
//            //关闭后 从map中移除
//            channelMap.remove(channelFuture.channel().id());
//            log.info("当前连接人数: {}", channelMap.size());
//        });
    }

    /**
     * 消息处理
     * @param ctx
     * @param msg
     * @param date
     */
    public void message(ChannelHandlerContext ctx, String msg, String date) {
        try {
            // 消息转发给在线的其他用户
            final String[] split = msg.split("\\|");
            Channel channel = ctx.channel();
            for (Channel tmpChannel : channelGroup) {
                if (!tmpChannel.equals(channel)) {
                    String sendedMsg = "来自[" + split[0] + "]：" + split[1];
                    log.info("服务器转发消息,客户端地址: {}, msg: {}", ctx.channel().remoteAddress(), sendedMsg);
                    tmpChannel.writeAndFlush(new TextWebSocketFrame(sendedMsg));
                }
            }
        } catch (Exception e) {
            log.error("message 处理异常， msg: {}, date: {}", msg, date, e);
        }
    }
}
